import {
  Component,
  OnInit,
  ViewEncapsulation,
  ChangeDetectionStrategy,
  Input,
  TemplateRef,
  Output,
  EventEmitter,
  AfterViewInit,
  SimpleChanges,
  ChangeDetectorRef,
  OnChanges,
  ViewChild,
} from '@angular/core';
import { I18NService, InputBoolean, InputNumber, LvSizeLSD, TypeUtils } from '../core/api';
import {
  ModeType,
  TransferBelong,
  TransferColumnItem,
  TransferModeTypeEnum,
  TransferTypeEnum,
} from './transfer.interface';
import { TransferTableComponent } from './transfer-table.component';
import { PaginatorComponent } from './../pagination/api';

@Component({
  selector: 'lv-transfer-panel',
  templateUrl: './transfer-panel.component.html',
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: {
    class: 'lv-transfer-panel',
    '[class.lv-transfer-panel-default]': 'lvMode === transferModeTypeEnum.DEFAULT',
  },
})
export class TransferPanelComponent implements OnInit, AfterViewInit, OnChanges {
  @Input() lvData: any[]; // 数据

  @Input() lvShowItemTotal;

  @Input() lvDataKey: string; // 唯一标识，用于data被选中的比较

  @Input() @InputNumber() lvTotal;

  @Input() lvBelong: TransferBelong;

  @Input() @InputNumber() lvItemSize = 5; // 每页条数

  @Input() lvSize: LvSizeLSD = 'default'; // size

  @Input() lvColumns: TransferColumnItem[];

  @Input() @InputBoolean() lvAsync = false;

  @Input() @InputBoolean() lvShowFilter = true;

  @Input() @InputBoolean() lvShowColControl = true; // 是否显示列显示隐藏配置

  @Input() lvSelection: Array<{ [key: string]: any }> = [];

  @Input() lvTitle: string | TemplateRef<void> | null;

  @Output() lvBelongChange = new EventEmitter<string>();

  @Input() lvMode: ModeType = TransferModeTypeEnum.DEFAULT;

  @Input() lvHeader: TemplateRef<{ $implicit: any }> | null;

  @Input() lvRender: TemplateRef<{ $implicit: any }> | null;

  @Input() lvFooter: TemplateRef<{ $implicit: any }> | null = null;

  @Output() lvRemoveItem = new EventEmitter<{ [key: string]: any }>();

  @Output() lvStateChange = new EventEmitter<{ [key: string]: any }>();

  @Output() lvSelectionChange = new EventEmitter<Array<{ [key: string]: any }>>();

  @ViewChild('transferTable', { static: false }) transferTable: TransferTableComponent;

  @Output() colDisplayChange = new EventEmitter<{
    currentCol: TransferColumnItem;
    displayCols: TransferColumnItem[];
  }>();

  @Input() lvOperateTemplate: TemplateRef<{
    $implicit: Array<{ [key: string]: any }>;
    selection: Array<{ [key: string]: any }>;
    paginator: PaginatorComponent;
    panel: TransferTableComponent;
  }>;

  total = 0;
  public typeUtils = TypeUtils;
  belong: TransferBelong = 'source';
  public transferTypeEnum = TransferTypeEnum;

  public maximum: number = Number.MAX_SAFE_INTEGER;
  public transferModeTypeEnum = TransferModeTypeEnum;

  constructor(
    private cdr: ChangeDetectorRef,
    public i18n: I18NService,
  ) {}

  get data(): any[] {
    if (this.lvMode === TransferModeTypeEnum.SIMPLE) {
      return this.belong === 'source' ? this.lvData : this.lvSelection;
    } else {
      return this.lvData;
    }
  }

  ngOnInit(): void {}

  DeleteAll(): void {
    this.removeItem(this.lvData);
  }

  removeItem(data): void {
    this.lvRemoveItem.emit(data);
  }

  stateChange(params): void {
    this.lvStateChange.emit(params);
  }

  changeBelong(belong: string): void {
    this.lvBelongChange.emit(belong);
  }

  selectionChange(selection): void {
    this.lvSelectionChange.emit(selection);
  }

  ngAfterViewInit(): void {
    if (!this.lvAsync) {
      this.total = this.lvData?.length;
    } else {
      this.total = this.lvTotal;
    }
  }

  ngOnChanges(changes: SimpleChanges): void {
    const { lvData, lvTotal, lvAsync, lvBelong: belongChange } = changes;

    const flag =
      (lvData && !lvData.firstChange) || (lvTotal && !lvTotal.firstChange) || (lvAsync && !lvAsync.firstChange);
    if (flag) {
      this.total = this.lvAsync ? this.lvTotal : this.lvData.length;
    }

    if (belongChange?.currentValue) {
      this.belong = belongChange.currentValue;
    }

    this.cdr.markForCheck();
  }

  selectAll(): void {
    if (this.lvAsync) {
      const selectMap = new Map();
      const cacheSelection = this.lvSelection.concat(this.lvData.filter((item): boolean => !item.disabled));
      cacheSelection.forEach((select): Map<any, any> => selectMap.set(select[this.lvDataKey], select));
      this.lvSelection = [...selectMap.values()];
    } else {
      this.lvSelection = this.lvData.filter((item): boolean => !item.disabled);
    }
    this.selectionChange(this.lvSelection);
  }
}
